package li.kaeppe.travel.tracker.domain;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;

import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

@Entity
@Table(name="TRIP",
		uniqueConstraints = {@UniqueConstraint(columnNames={"TRIP_KEY"})}
)
@javax.persistence.SequenceGenerator(name="SEQ_TRIP", sequenceName="TRIP_SEQUENCE")
public class Trip implements Serializable {

	/* **************************************************** */
	/*                      CONSTANTS                       */
	/* **************************************************** */
	
	private static final long serialVersionUID = -706137324672920509L;

	/* **************************************************** */
	/*                     MEMBER FIELDS                    */
	/* **************************************************** */

	@Id @GeneratedValue(strategy=GenerationType.AUTO, generator="SEQ_TRIP")
	private long id;
	
	@Column(name="TRIP_KEY", nullable=false, length=128)
	private String key;
	
	@Basic
	private String title;
	
	@Column(nullable=true, length=4096)
	private String description;
	
	@Basic
	private Date startDate;
	
	@Basic
	private Date endDate;
	
	@OneToMany(mappedBy="trip", fetch = FetchType.LAZY, cascade= {CascadeType.ALL}) 
	@OrderBy("date DESC")
	private Collection<WayPoint> wayPoints;
	
//	@OneToMany(mappedBy="wayPoint.trip", fetch = FetchType.LAZY, cascade= {CascadeType.ALL}) 
//	@OrderBy("date DESC")
//	private Collection<BlogEntry> blogEntries;
	
	/* **************************************************** */
	/*                      CONSTRUCTOR                     */
	/* **************************************************** */
	
	public Trip() {
		super();
		this.wayPoints = new ArrayList<WayPoint>();
	}
	
	public Trip(String key, String title, String description, Date startDate, Date endDate) {
		this();
		this.key = key;
		this.title = title;
		this.description = description;
		this.startDate = startDate;
		this.endDate = endDate;
	}
	
	public Trip(long id, String key, String title, String description, Date startDate, Date endDate) {
		this(key, title, description, startDate, endDate);
		this.id = id;
	}
	
	public Trip(long id, String key, String title, String description, Date startDate, Date endDate, Collection<WayPoint> wayPoints) {
		this(id, key, title, description, startDate, endDate);
		this.wayPoints = wayPoints;
	}
	
	public Trip(Trip trip) {
		this(trip.id, 
			 trip.key,
			 trip.title,
			 trip.description,
			 trip.startDate,
			 trip.endDate,
			 trip.wayPoints);
	}
	
	/* **************************************************** */
	/*                    PUBLIC METHODS                    */
	/* **************************************************** */
	
	public void addWayPoint(WayPoint wayPoint) {
		wayPoint.setTrip(this);
		this.getWayPoints().add(wayPoint);
	}
	
	public void addWayPoints(Collection<WayPoint> wayPoints) {
		for(WayPoint wayPoint : wayPoints) {
			this.addWayPoint(wayPoint);
		}
	}
	
//	public void addBlogEntry(BlogEntry blogEntry) {
//		blogEntry.setTrip(this);
//		this.getBlogEntries().add(blogEntry);
//	}
	
	public String toString() {
		StringBuffer buffer = new StringBuffer();
		
		buffer.append("id=");
		buffer.append(this.getId());
		buffer.append(",title=");
		buffer.append(this.getTitle());
		buffer.append(",description=");
		buffer.append(this.getDescription());
		buffer.append(",startDate=");
		buffer.append(this.getStartDate());
		buffer.append(",endDate=");
		buffer.append(this.getEndDate());
		buffer.append(", wayPoints [");
		/*for(WayPoint wayPoint : this.getWayPoints()) {
			buffer.append(wayPoint.toString());
			buffer.append(',');
		}*/
		buffer.append("]");
		
		return buffer.toString();
	}
	
	public boolean equals(Object object) {
		boolean equals = false;
		
		if(object instanceof Trip) {
			Trip trip = (Trip)object;
			equals = (this.getId() == trip.getId()) &&
					 (this.getTitle().equals(trip.getTitle())) &&
					 (this.getDescription().equals(trip.getDescription())) &&
					 (this.getStartDate().equals(trip.getStartDate())) &&
					 (this.getEndDate().equals(trip.getEndDate()));
		}
		
		return equals;
	}
	
	/* **************************************************** */
	/*                  PROTECTED METHODS                   */
	/* **************************************************** */

	/* **************************************************** */
	/*                   PRIVATE METHODS                    */
	/* **************************************************** */

	/* **************************************************** */
	/*                  GETTERS AND SETTERS                 */
	/* **************************************************** */

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public Date getEndDate() {
		return endDate;
	}

	public void setEndDate(Date endDate) {
		this.endDate = endDate;
	}

	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public Date getStartDate() {
		return startDate;
	}

	public void setStartDate(Date startDate) {
		this.startDate = startDate;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public Collection<WayPoint> getWayPoints() {
		return wayPoints;
	}
	
	/** 
	 * Use addWayPoint() and addWayPoints() instead of setWayPoints() 
	 */
	protected void setWayPoints(Collection<WayPoint> wayPoints) {
		this.wayPoints = wayPoints;
	}

	public String getKey() {
		return key;
	}

	public void setKey(String key) {
		this.key = key;
	}

//	public Collection<BlogEntry> getBlogEntries() {
//		return blogEntries;
//	}
//	
//	/** 
//	 * User addBlogEntry instead of setBlogEntries 
//	 */
//	public void setBlogEntries(Collection<BlogEntry> blogEntries) {
//		this.blogEntries = blogEntries;
//	}	
}
